/*
 * Copyright 2009 Cedric Priscal
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License. 
 */

/*
* 专门为Brandon添加的串口界面
* */

package android.serialport.sample;

import android.os.Bundle;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.TextView.OnEditorActionListener;
import android.widget.Toast;

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

public class CoinStorageActivity extends SerialPortActivity {

    EditText mReception;
    EditText mEmission;
    CheckBox mHexCheck;
    CheckBox mNewLineCheck;
    Button mBtnClear;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.coin_storage);

        //		setTitle("Loopback test");
        mReception = (EditText) findViewById(R.id.EditTextReception);
        mEmission = (EditText) findViewById(R.id.EditTextEmission);
        mHexCheck = (CheckBox) findViewById(R.id.checkBoxHex);
        mNewLineCheck = (CheckBox) findViewById(R.id.checkBoxNewLine);
        mBtnClear = (Button) findViewById(R.id.buttonClear);

        EditText Emission = (EditText) findViewById(R.id.EditTextEmission);
        Emission.setOnEditorActionListener(new OnEditorActionListener() {
            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
                int i;
                CharSequence t = v.getText();
                char[] text = new char[t.length()];
                for (i = 0; i < t.length(); i++) {
                    text[i] = t.charAt(i);
                }
                try {
                    mOutputStream.write(new String(text).getBytes());
                    mOutputStream.write('\n');
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return false;
            }
        });

        //绑定监听器
        mHexCheck.setOnCheckedChangeListener(new CheckBox.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                // TODO Auto-generated method stub
                Toast.makeText(CoinStorageActivity.this, isChecked ? "选中了" : "取消了选中", Toast.LENGTH_LONG).show();

            }
        });

        mBtnClear.setOnClickListener(new View.OnClickListener() {
            public void onClick(View v) {
                mReception.setText("");
            }
        });


        findViewById(R.id.btnBccErr).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                bccErr();
            }
        });
        findViewById(R.id.btnCmd).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                cmd();
            }
        });
        findViewById(R.id.btnPay).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                pay();
            }
        });

        findViewById(R.id.btnDepSmall).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                depSmall();
            }
        });
        findViewById(R.id.btnDepMedivon).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                depMedium();
            }
        });
        findViewById(R.id.btnDepLarge).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                depLarge();
            }
        });
        findViewById(R.id.btnRetrieve).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                retrieve();
            }
        });
        findViewById(R.id.btnMgm).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                mgm();
            }
        });
        findViewById(R.id.btnTest1).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                test1();
            }
        });
        findViewById(R.id.btnTest2).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                test2();
            }
        });
        findViewById(R.id.btnAddSeq).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                addSeq();
            }
        });
    }

    //检验和。从STX开始到Info最后一字节异或
    private byte[] bcc(byte[] data) {
        byte bcc = 0;
        for (int i=0;i<data[1]-2;i++) {
            bcc ^= data[i];
        }
        data[data[1]-2] = bcc;
        return data;
    }

    private String bccCheck(byte[] data){
        byte bcc = 0;
        for (int i=0;i<data[1]-2;i++) {
            bcc ^= data[i];
        }
        if(bcc != data[data[1]-2])
            return " <BCC Err>";
        else
            return " <BCC OK>";
    }

    private void autoSetSeq(byte[] data)
    {
        EditText seq1 = (EditText) findViewById(R.id.seq1);
        EditText seq2 = (EditText) findViewById(R.id.seq2);
        int seq = data[3];
        seq1.setText(seq+"");
        seq2.setText(seq+"");
    }

    private void addSeq() {
        EditText seq2 = (EditText) findViewById(R.id.seq2);
        String seq2Text = seq2.getText().toString();
        if (TextUtils.isEmpty(seq2Text)) {
            seq2.setText("0");
        } else {
            int seq = Integer.parseInt(seq2Text);
            seq++;
            seq2.setText(seq+"");
        }
    }

    private void test1() {
        try {
            byte[] cmd = {0x02, 0x09, (byte) 0xa1, 0x02, 0x00, 0x01, 0x02, (byte)0xAB, 0x03};
            mOutputStream.write(cmd);
            mOutputStream.write('\n');

        } catch (Exception e) {
            Toast.makeText(this, "发送指令失败", Toast.LENGTH_LONG).show();
            Log.e("CoinStorage", "发送指令失败", e);
        }
    }
    private void test2() {
        try {
            byte[] cmd = {0x02, 0x09, (byte) 0xa1, 0x02, 0x00, 0x01, 0x0A, (byte)0xA3, 0x03};
            mOutputStream.write(cmd);

        } catch (Exception e) {
            Toast.makeText(this, "发送指令失败", Toast.LENGTH_LONG).show();
            Log.e("CoinStorage", "发送指令失败", e);
        }
    }

    //【非管理 操作】
    // 《Retrieve》按钮，设TT=04，输入nn（反显上次nn值，点击递增）
    private void retrieve() {
        //mReception.append("Retrieve: ");
        EditText seq2 = (EditText) findViewById(R.id.seq2);
        String seq2Text = seq2.getText().toString();
        if (!TextUtils.isEmpty(seq2Text)) {
            byte seqByte = (byte) Integer.parseInt(seq2Text.trim(), 16);
            byte TT = 0x04;
            byte bcc = 0x00;
            try {
                byte[] cmd = {0x02, 0x09, (byte) 0xa1, seqByte, 0x10, 0x01, TT, bcc, 0x03};
                bcc(cmd);
                mOutputStream.write(cmd);

                String bufferData;
                bufferData = toHexString(cmd, 9);
                mEmission.append("Retrieve: ");
                mEmission.append(simpleDateString() + ":   ");
                mEmission.append(bufferData);
                mEmission.append(getAppCode(cmd));
                mEmission.append("\r\n");
            } catch (Exception e) {
                Toast.makeText(this, "发送指令失败", Toast.LENGTH_LONG).show();
                Log.e("CoinStorage", "发送指令失败", e);
            }
        } else {
            Toast.makeText(this, "请输入SEQ值", Toast.LENGTH_LONG).show();
        }
    }

    private void mgm() {
        EditText seq2 = (EditText) findViewById(R.id.seq2);
        String seq2Text = seq2.getText().toString();
        if (!TextUtils.isEmpty(seq2Text)) {
            byte seqByte = (byte) Integer.parseInt(seq2Text.trim(), 16);
            EditText etCode = (EditText) findViewById(R.id.etCode);
            String code = etCode.getText().toString();
            if (!TextUtils.isEmpty(code)) {
                if (code.length() == 8) {

                    char a1 = code.charAt(0);
                    char a2 = code.charAt(1);
                    char a3 = code.charAt(2);
                    char a4 = code.charAt(3);
                    char a5 = code.charAt(4);
                    char a6 = code.charAt(5);
                    char a7 = code.charAt(6);
                    char a8 = code.charAt(7);

                    byte b1 = (byte) a1;
                    byte b2 = (byte) a2;
                    byte b3 = (byte) a3;
                    byte b4 = (byte) a4;
                    byte b5 = (byte) a5;
                    byte b6 = (byte) a6;
                    byte b7 = (byte) a7;
                    byte b8 = (byte) a8;

                    //Log.d("CoinStorage", "" + b1 + " " + b2 + " " + b3 + " " + b4 + " " + b5 + " " + b6 + " " + b7 + " " + b8 + " ");
                    byte bcc = 0x00;
                    try {
                        byte [] cmd = {0x02, 0x11,(byte)0xa1, seqByte, 0x10, 0x09, 0x00, b1,b2,b3,b4,b5,b6,b7,b8,bcc,0x03};
                        bcc(cmd);
                        mOutputStream.write(cmd);
                        seqByte++;
                        seq2.setText(seqByte + "");

                        String bufferData;
                        bufferData = toHexString(cmd, 16);
                        mEmission.append("Mgm+: ");
                        mEmission.append(simpleDateString() + ":   ");
                        mEmission.append(bufferData);
                        mEmission.append(getAppCode(cmd));
                        mEmission.append("\r\n");
                    } catch (Exception e) {
                        Toast.makeText(this, "发送指令失败", Toast.LENGTH_LONG).show();
                        Log.e("CoinStorage", "发送指令失败", e);
                    }
                } else {
                    Toast.makeText(this, "code必须为8位", Toast.LENGTH_LONG).show();
                }
            } else {
                Toast.makeText(this, "请输入code值", Toast.LENGTH_LONG).show();
            }
        } else {
            Toast.makeText(this, "请输入SEQ值", Toast.LENGTH_LONG).show();
        }

    }

    //【非管理 操作】
    // 《Dep Large》按钮，设TT=03，输入nn（反显上次nn值，点击递增）
    private void depLarge() {
        //mReception.append("Dep Large: ");
        EditText seq2 = (EditText) findViewById(R.id.seq2);
        String seq2Text = seq2.getText().toString();
        if (!TextUtils.isEmpty(seq2Text)) {
            byte seqByte = (byte) Integer.parseInt(seq2Text.trim(), 16);
            byte TT = 0x03;
            byte bcc = 0x00;
            try {
                byte[] cmd = {0x02, 0x09, (byte) 0xa1, seqByte, 0x10, 0x01, TT, bcc, 0x03};
                bcc(cmd);
                mOutputStream.write(cmd);

                String bufferData;
                bufferData = toHexString(cmd, 9);
                mEmission.append("Dep Large: ");
                mEmission.append(simpleDateString() + ":   ");
                mEmission.append(bufferData);
                mEmission.append(getAppCode(cmd));
                mEmission.append("\r\n");
            } catch (Exception e) {
                Toast.makeText(this, "发送指令失败", Toast.LENGTH_LONG).show();
                Log.e("CoinStorage", "发送指令失败", e);
            }
        } else {
            Toast.makeText(this, "请输入SEQ值", Toast.LENGTH_LONG).show();
        }
    }

    //【非管理 操作】
    // 《Dep Medium》按钮，设TT=02，输入nn（反显上次nn值，点击递增）
    private void depMedium() {
        //mReception.append("Dep Medium: ");
        EditText seq2 = (EditText) findViewById(R.id.seq2);
        String seq2Text = seq2.getText().toString();
        if (!TextUtils.isEmpty(seq2Text)) {
            byte seqByte = (byte) Integer.parseInt(seq2Text.trim(), 16);
            byte TT = 0x02;
            byte bcc = 0x00;
            try {
                byte[] cmd = {0x02, 0x09, (byte) 0xa1, seqByte, 0x10, 0x01, TT,bcc, 0x03};
                bcc(cmd);
                mOutputStream.write(cmd);


                String bufferData;
                bufferData = toHexString(cmd, 9);
                mEmission.append("Dep Medium: ");
                mEmission.append(simpleDateString() + ":   ");
                mEmission.append(bufferData);
                mEmission.append(getAppCode(cmd));
                mEmission.append("\r\n");
            } catch (Exception e) {
                Toast.makeText(this, "发送指令失败", Toast.LENGTH_LONG).show();
                Log.e("CoinStorage", "发送指令失败", e);
            }
        } else {
            Toast.makeText(this, "请输入SEQ值", Toast.LENGTH_LONG).show();
        }
    }

    //非管理 操作】
    //《Dep Small》按钮，设TT=01，输入nn（反显上次nn值，点击递增）
    private void depSmall() {
        //mReception.append("Dep Small: ");
        EditText seq2 = (EditText) findViewById(R.id.seq2);
        String seq2Text = seq2.getText().toString();
        if (!TextUtils.isEmpty(seq2Text)) {
            byte seqByte = (byte) Integer.parseInt(seq2Text.trim(), 16);
            byte TT = 0x01;
            byte bcc = 0x00;
            try {
                byte[] cmd = {0x02, 0x09, (byte) 0xa1, seqByte, 0x10, 0x01, TT,bcc, 0x03};
                bcc(cmd);
                mOutputStream.write(cmd);

                String bufferData;
                bufferData = toHexString(cmd, 9);
                mEmission.append("Dep Small: ");
                mEmission.append(simpleDateString() + ":   ");
                mEmission.append(bufferData);
                mEmission.append(getAppCode(cmd));
                mEmission.append("\r\n");
            } catch (Exception e) {
                Toast.makeText(this, "发送指令失败", Toast.LENGTH_LONG).show();
                Log.e("CoinStorage", "发送指令失败", e);
            }

        } else {
            Toast.makeText(this, "请输入SEQ值", Toast.LENGTH_LONG).show();
        }
    }

    //《Pay》按钮，输入nn（反显最后接收到的nn值）+金额YY
    private void pay() {
        //mReception.append("Pay: ");
        try {
            EditText et = (EditText) findViewById(R.id.etMoney);
            byte money = (byte) Integer.parseInt(et.getText().toString().trim());
            EditText seq = (EditText) findViewById(R.id.seq1);
            byte seqByte = (byte) Integer.parseInt(seq.getText().toString().trim(), 16);
            byte bcc = 0x00;
            byte[] cmd = {0x02, 0x09, (byte) 0xa1, seqByte, 0x00, 0x01, money,bcc, 0x03};
            bcc(cmd);
            mOutputStream.write(cmd);

            String bufferData;
            bufferData = toHexString(cmd, 9);
            mEmission.append("Pay: ");
            mEmission.append(simpleDateString() + ":   ");
            mEmission.append(bufferData);
            mEmission.append(getAppCode(cmd));
            mEmission.append("\r\n");
        } catch (Exception e) {
            Toast.makeText(this, "发送指令失败", Toast.LENGTH_LONG).show();
            Log.e("CoinStorage", "发送指令失败", e);
        }
    }

    //《Cmd N/A》按钮，输入nn（反显最后接收到的nn值）
    private void cmd() {
        //mReception.append("Cmd N/A: ");
        try {
            EditText seq = (EditText) findViewById(R.id.seq1);
            byte seqByte = (byte) Integer.parseInt(seq.getText().toString().trim(), 16);
            byte bcc= 0x00;
            byte[] cmd = {0x02, 0x08, (byte) 0xa1, seqByte, 0x02, 0x00,bcc, 0x03};
            bcc(cmd);
            mOutputStream.write(cmd);

            String bufferData;
            bufferData = toHexString(cmd, 8);
            mEmission.append("Cmd N/A: ");
            mEmission.append(simpleDateString() + ":   ");
            mEmission.append(bufferData);
            mEmission.append(getAppCode(cmd));
            mEmission.append("\r\n");
        } catch (Exception e) {
            Toast.makeText(this, "发送指令失败", Toast.LENGTH_LONG).show();
            Log.e("CoinStorage", "发送指令失败", e);
        }
    }

    //《BCC Err》按钮，输入nn（反显最后接收到的nn值）
    private void bccErr() {
        //mReception.append("BCC Err: ");
        try {
            EditText seq = (EditText) findViewById(R.id.seq1);
            byte seqByte = (byte) Integer.parseInt(seq.getText().toString().trim(), 16);
            byte bcc = 0x00;
            byte[] cmd = {0x02, 0x08, (byte) 0xa1, seqByte, 0x01, 0x00,bcc, 0x03};
            bcc(cmd);
            mOutputStream.write(cmd);

            String bufferData;
            bufferData = toHexString(cmd, 8);
            mEmission.append("BCC Err: ");
            mEmission.append(simpleDateString() + ":   ");
            mEmission.append(bufferData);
            mEmission.append(getAppCode(cmd));
            mEmission.append("\r\n");
        } catch (Exception e) {
            Toast.makeText(this, "发送指令失败", Toast.LENGTH_LONG).show();
            Log.e("CoinStorage", "发送指令失败", e);
        }
    }


    @Override
    protected void onDataReceived(final byte[] buffer, final int size) {
        runOnUiThread(new Runnable() {
            public void run() {
                String bufferData;
                if (mHexCheck.isChecked()) {
                    bufferData = toHexString(buffer, size);
                } else {
                    bufferData = new String(buffer, 0, size);
                }
                if (mReception != null) {
                    mReception.append(simpleDateString() + ":   ");
                    mReception.append(bufferData);
                    mReception.append(getAppCode(buffer));
                    //mReception.append(bccCheck(buffer));
                    if (mNewLineCheck.isChecked())
                        mReception.append("\r\n");
                    //自动填充 SEQ
                    autoSetSeq(buffer);
                }
            }
        });
    }

    /**
     *
     /**
     * 从一个byte[]数组中截取一部分
     * @param src
     * @param begin
     * @param count
     * @return
     */
    public static byte[] subBytes(byte[] src, int begin, int count) {
        byte[] bs = new byte[count];
        for (int i=begin; i<begin+count; i++) bs[i-begin] = src[i];
        return bs;
    }

    private String getAppCode(byte[] data)
    {
        byte[] appCode = subBytes(data, 3, data[5]+3);
        //return " [AppCode: " +toHexString(appCode, data[5]+3) + "<CR>]";
        return " [AppCode: " +toHexString(appCode, data[5]+3) + "]";
    }

    private String simpleDateString()
    {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");// HH:mm:ss
//获取当前时间
        Date date = new Date(System.currentTimeMillis());
        return simpleDateFormat.format(date);
        //time1.setText("Date获取当前日期时间"+simpleDateFormat.format(date));
    }

    /**
     * 将byte[]数组转化为String类型
     *
     * @param arg    需要转换的byte[]数组
     * @param length 需要转换的数组长度
     * @return 转换后的String队形
     */
    private String toHexString(byte[] arg, int length) {
        String result = new String();
        if (arg != null) {
            for (int i = 0; i < length; i++) {
                result = result
                        + (Integer.toHexString(
                        arg[i] < 0 ? arg[i] + 256 : arg[i]).length() == 1 ? "0"
                        + Integer.toHexString(arg[i] < 0 ? arg[i] + 256
                        : arg[i])
                        : Integer.toHexString(arg[i] < 0 ? arg[i] + 256
                        : arg[i])) + " ";
            }
            return result;
        }
        return "";
    }
}
